﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using MongoDB.Driver.Linq;
using nMongo.Tests.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace nMongo.Tests
{
    [TestClass]
    public class MongoEngineTests
    {
        #region Fatories
        [TestMethod]
        public void ConstructorFirstOverload()
        {
            MongoEngine engine = new MongoEngine(TestsConfiguration.ConnectionString, TestsConfiguration.DatabaseName);

            // Assert the constructor process
            Assert.AreEqual(engine.ConnectionString, TestsConfiguration.ConnectionString);
            Assert.AreEqual(engine.Database.Name, TestsConfiguration.DatabaseName);
            Assert.AreEqual(engine.PersistencyControlEnabled, MongoPersistencyOptions.Disabled);
        }

        [TestMethod]
        public void ConstructorSecondOverload()
        {
            MongoEngine engine = new MongoEngine(TestsConfiguration.ConnectionString, TestsConfiguration.DatabaseName, MongoPersistencyOptions.Mixed);

            // Assert the constructor process
            Assert.AreEqual(engine.ConnectionString, TestsConfiguration.ConnectionString);
            Assert.AreEqual(engine.Database.Name, TestsConfiguration.DatabaseName);
            Assert.AreEqual(engine.PersistencyControlEnabled, MongoPersistencyOptions.Mixed);
        }

        [TestMethod]
        public void BuildConnection()
        {
            MongoEngine engine = new MongoEngine(TestsConfiguration.ConnectionString, TestsConfiguration.DatabaseName);
            engine.BuildConnection(TestsConfiguration.ConnectionString2, TestsConfiguration.DatabaseName2);

            // Assert the method
            Assert.AreEqual(engine.ConnectionString, TestsConfiguration.ConnectionString2);
            Assert.AreEqual(engine.Database.Name, TestsConfiguration.DatabaseName2);
        }

        // TODO: Test the BuildConnectionFromAppConfig method 
        #endregion
        
        #region Methods

        [TestMethod]
        public void GetCollection()
        {
            MongoEngine engine = new MongoEngine(TestsConfiguration.ConnectionString, TestsConfiguration.DatabaseName);
            MongoCollection<User> collection = engine.GetCollection<User>();
            collection.Insert(new User { Age = 77, IsActive = true, Name = "Tester Man" });

            // Assert
            Assert.IsNotNull(collection.AsQueryable().FirstOrDefault(x => x.Name == "Tester Man"));

            // Revert & Assert Revert
            collection.Remove(Query.EQ("Name", BsonValue.Create("Tester Man")));
            Assert.IsNull(collection.AsQueryable().FirstOrDefault(x => x.Name == "Tester Man"));
        }

        [TestMethod]
        public void RequestStartBothOverloads()
        {
            MongoEngine engine = new MongoEngine(TestsConfiguration.ConnectionString, TestsConfiguration.DatabaseName);
            MongoCollection<User> collection = engine.GetCollection<User>();

            using (engine.RequestStart())
            {
                collection.Insert(new User { Age = 88, IsActive = true, Name = "Tester Man 1" });
                collection.Insert(new User { Age = 99, IsActive = false, Name = "Tester Man 2" });
            };
            using (engine.RequestStart(ReadPreference.Nearest))
            {
                collection.Insert(new User { Age = 88, IsActive = true, Name = "Tester Man 3" });
                collection.Insert(new User { Age = 99, IsActive = false, Name = "Tester Man 4" });
            };

            // Revert & Assert Revert
            collection.Remove(Query.EQ("Name", BsonValue.Create("Tester Man 1")));
            collection.Remove(Query.EQ("Name", BsonValue.Create("Tester Man 2")));
            collection.Remove(Query.EQ("Name", BsonValue.Create("Tester Man 3")));
            collection.Remove(Query.EQ("Name", BsonValue.Create("Tester Man 4")));
            Assert.IsNull(collection.AsQueryable().FirstOrDefault(x => x.Name == "Tester Man 1"));
            Assert.IsNull(collection.AsQueryable().FirstOrDefault(x => x.Name == "Tester Man 2"));
            Assert.IsNull(collection.AsQueryable().FirstOrDefault(x => x.Name == "Tester Man 3"));
            Assert.IsNull(collection.AsQueryable().FirstOrDefault(x => x.Name == "Tester Man 4"));
        }
        #endregion
    }
}
